﻿#ifndef DRAWPATHWIDGET_H
#define DRAWPATHWIDGET_H

#include <QWidget>
#include <QTimer>
#include <osgQt/GraphicsWindowQt>   /// osgQt::GraphicsWindowQt
#include <osgViewer/Viewer>         /// osgViewer::Viewer
#include <osgDB/ReadFile>           /// osg::ref_ptr
#include <osgUtil/PlaneIntersector> /// osgUtil::PlaneIntersector
#include <osg/ShapeDrawable>                /// osg::ShapeDrawable


class DrawPathWidget : public QWidget
{
    Q_OBJECT

    public:

        explicit DrawPathWidget(QWidget *parent = nullptr);

        virtual ~DrawPathWidget();

        /** 根据缓存的轨迹点数组绘制轨迹 */
        void setPathPoint(const std::vector<std::vector<float>>& vex);

        /** 载入轨迹 */
        void open(const QString& fileName);

        /** 删除轨迹 */
        void close(const QString& fileName);

        /** 获取相交点数组 */
        QVector<osg::Vec3d> getIntersectorPoint(const osg::Vec3d& startPoint, const osg::Vec3d& endPoint, const osg::Vec3d& upVector);


    protected:

        inline void resizeEvent(QResizeEvent* event) {
            Q_UNUSED(event);
            update();
        }

        inline void paintEvent( QPaintEvent* event ) {
            Q_UNUSED(event);
            (*pViewer).frame();
        }


    private:

        void init();

        void layout();

        void drawPath();

        bool readFile(const QString& fileName);

        /** 在点坐标处渲染一个球 */
        void drawPoint(const osg::Vec3d& point);

        /** 根据起点 终点 方向向量 创建一个求交面 */
        osg::ref_ptr<osgUtil::PlaneIntersector> createPlaneIntersector(const osg::Vec3d& startPoint,
                                                                       const osg::Vec3d& endPoint,
                                                                       const osg::Vec3d& upVector);

        /** 根据起点和终点的连线创建一个胶囊体渲染对象 */
        osg::ref_ptr<osg::ShapeDrawable> getCapsuleDrawableWithPoint(const osg::Vec3d& point1, const osg::Vec3d& point2);

        osg::ref_ptr<osgQt::GraphicsWindowQt> createGraphicsWindow(int x, int y, int w, int h);

        /** 根据第一条轨迹的极限范围绘制格栅 */
        osg::ref_ptr<osg::Geode> initCoordinate(const float& xMinLimit, const float& xMaxLimit,
                                                const float& yMinLimit, const float& yMaxLimit,
                                                const float& zMinLimit, const float& zMaxLimit,
                                                const int& step);

        /** 按照字符ch分割一行字符串 */
        std::vector<float> splitString(const QString& line, const char& ch);


        /** 配置映射环境 */
        void setMapping(float XMinLimit, float XMaxLimit, float YMinLimit, float YMaxLimit,
                                        float ZMinLimit, float ZMaxLimit, int n);


        /** 获取映射后的坐标 */
        osg::Vec3f mapping(std::vector<float> point);

        /** 获取映射前的坐标 */
        osg::Vec3f unMapping(osg::Vec3f point);


    private:

        std::string fileName;                           /// 记录当前所选中的文件名称

        osg::ref_ptr<osgViewer::Viewer> pViewer;

        osg::ref_ptr<osgQt::GraphicsWindowQt> pWindow;

        osg::ref_ptr<osg::Vec3Array> pointsArray;       /// 缓存轨迹点的数组

        QTimer timer;                                   /// 通过定时器来刷新osg屏幕,相当于帧率

        float XMinLimit;        /// 轨迹点实际坐标的范围
        float XMaxLimit;
        float YMinLimit;
        float YMaxLimit;
        float ZMinLimit;
        float ZMaxLimit;

        int n;                  ///轨迹在z坐标轴中间的占比 例如: 1为100% 3为33% 5为20%
};

#endif // DRAWPATHWIDGET_H
